package com.lytoyo.neihanduanzi.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lytoyo.neihanduanzi.mapper.BlogMapper;
import com.lytoyo.neihanduanzi.mapper.UserAttentionMapper;
import com.lytoyo.neihanduanzi.mapper.UserMapper;
import com.lytoyo.neihanduanzi.model.blog.BlogInfo;
import com.lytoyo.neihanduanzi.model.dto.BlogInfoDto;
import com.lytoyo.neihanduanzi.model.user.ChatMsg;
import com.lytoyo.neihanduanzi.model.user.UserAttention;
import com.lytoyo.neihanduanzi.model.user.UserInfo;
import com.lytoyo.neihanduanzi.service.BlogService;
import com.lytoyo.neihanduanzi.service.ChatMsgService;
import com.lytoyo.neihanduanzi.service.UserAttentionService;
import com.lytoyo.neihanduanzi.service.UserService;
import com.lytoyo.neihanduanzi.utils.Constant;
import com.lytoyo.neihanduanzi.utils.WebsocketLocalContainerUtil;
import jakarta.annotation.Resource;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.MessagePropertiesBuilder;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Package:com.lytoyo.neihanduanzi.controller
 *
 * @ClassName:AttentionWebsocketController
 * @Create:2025/4/29 11:11
 **/

@Component
@ServerEndpoint(value = "/attention/{userId}")
@Slf4j
public class AttentionWebsocketController {
    private static RedisTemplate redisTemplate;

    private static UserService userService;


    private static BlogMapper blogMapper;

    private static UserMapper userMapper;

    @Autowired
    public void setUserMapper(UserMapper userMapper){
        AttentionWebsocketController.userMapper = userMapper;
    }

    @Autowired
    public void setBlogMapper(BlogMapper blogMapper){
        AttentionWebsocketController.blogMapper = blogMapper;
    }


    @Autowired
    public void setUserService(UserService userService) {
        AttentionWebsocketController.userService = userService;
    }

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        AttentionWebsocketController.redisTemplate = redisTemplate;
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Long userId) {
        //获取用户基本信息
        UserInfo userInfo = (UserInfo) redisTemplate.opsForValue().get(Constant.USER_LOGIN_KEY + userId);
        if (null == userInfo) {
            userInfo = userService.getById(userId);
            if (null != userInfo) {
                redisTemplate.opsForValue().set(Constant.USER_LOGIN_KEY + userId, userInfo, Constant.USER_LOGIN_TTL, TimeUnit.SECONDS);
            }
        }
        //将用户信息关联容器
        WebsocketLocalContainerUtil.addAttentionSession(userId, session);
        WebsocketLocalContainerUtil.addAttentionUser(userId, userInfo);
        this.pullOfflineMessages(userId);
    }


    @OnClose
    public void onClose(Session session, @PathParam("userId") Long userId) {
        log.info("用户{}断开连接", userId);
        //将用户信息移除容器
        WebsocketLocalContainerUtil.removeAttentionSession(userId);
        WebsocketLocalContainerUtil.removeAttentionUser(userId);
    }

    //当产生错误时候
    @OnError
    public void onError(Session session, Throwable e) {
        log.error("发生错误");
        e.printStackTrace();
    }

    /**
     * 上线后拉取未登录时候的消息
     *
     * @param userId
     */
    private void pullOfflineMessages(Long userId) {
        if (userId != null && redisTemplate.hasKey(Constant.USER_FOLLOW_BLOG_ID_KEY + userId)) {
            List<Long> blogIdList = redisTemplate.opsForList().range(Constant.USER_FOLLOW_BLOG_ID_KEY + userId, 0, -1);
            //通过博客id查询与之对应的用户id
            List<BlogInfo> list = blogMapper.selectList(new QueryWrapper<BlogInfo>().in("id", blogIdList).select("id","user_id"));

            //提取所有userId（去重）
            Set<Long> userIds = list.stream().map(BlogInfo::getUserId).collect(Collectors.toSet());

            //批量查询博客信息
            List<BlogInfo> blogList = blogMapper.selectBatchIds(blogIdList);

            //博客信息映射：blogId->Blog
            Map<Long, BlogInfo> blogMap = blogList.stream().collect(Collectors.toMap(BlogInfo::getId, blog -> blog));

            //批量查询用户信息
            List<UserInfo> userList = userMapper.selectBatchIds(userIds);

            //用户信息映射：userId->User
            Map<Long, UserInfo> userMap = userList.stream().collect(Collectors.toMap(UserInfo::getId, user -> user));

            //合并数据到BlogInfoDto
            List<BlogInfoDto> blogInfoDtoList = new ArrayList<>();
            list.forEach(blogInfo -> {
                BlogInfoDto blogInfoDto = new BlogInfoDto();
                BlogInfo info = blogMap.get(blogInfo.getId());

                if(null != info){
                    BeanUtils.copyProperties(info,blogInfoDto, BlogInfoDto.class);
                }
                UserInfo userInfo = userMap.get(blogInfo.getUserId());
                if(null != userInfo){
                    blogInfoDto.setHeadPhoto(userInfo.getHeadPhoto())
                               .setNickname(userInfo.getNickname());
                }
                blogInfoDtoList.add(blogInfoDto);
            });
            WebsocketLocalContainerUtil.sendFollowMsg(userId,blogInfoDtoList);
            if(redisTemplate.hasKey(Constant.USER_FOLLOW_BLOG_ID_KEY+userId)){
                redisTemplate.delete(Constant.USER_FOLLOW_BLOG_ID_KEY + userId);
            }
        }
    }


}
